package dungeonDigger.entities;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Line;
import org.newdawn.slick.geom.Vector2f;

import dungeonDigger.Tools.Rectangle;
import dungeonDigger.Tools.References;
import dungeonDigger.Tools.Toolbox;
import dungeonDigger.collisions.QuadCollisionEngine;
import dungeonDigger.contentGeneration.DungeonGenerator;

public abstract class GameObject {
	/** Actual pixel measurements **/
	private Vector2f			position		= new Vector2f();
	private Rectangle			collisionBox	= new Rectangle( 0, 0, 0, 0 );
	private QuadCollisionEngine	parentNode		= null;

	public abstract void update(GameContainer c, int d);

	public abstract void render(GameContainer c, Graphics g);

	public abstract float getWidth();

	public abstract float getHeight();

	public abstract Rectangle getDrawBox();

	public boolean isInLineOfSightOf(Agent agent) {
		Line lineOfSight = new Line( agent.getCenterPoint(), this.getNearestCornerTo( agent ) );
		Vector2f agentCell = agent.getMapCoordinates();
		Vector2f myCell = this.getMapCoordinates();
		int top = (int)Math.min( agentCell.getY(), myCell.getY() );
		int left = (int)Math.min( agentCell.getX(), myCell.getX() );
		int right = (int)Math.max( agentCell.getX(), myCell.getX() );
		int bottom = (int)Math.max( agentCell.getY(), myCell.getY() );
		top = top > 0 ? top - 1 : top;
		left = left > 0 ? left - 1 : left;
		right = right >= References.CLIENT_VIEW.getDungeonWidth() ? References.CLIENT_VIEW.getDungeonWidth() - 1 : right + 1;
		bottom = bottom >= References.CLIENT_VIEW.getDungeonHeight() ? References.CLIENT_VIEW.getDungeonWidth() - 1 : bottom + 1;
		for( int row = top; row <= bottom; row++ ) {
			for( int col = left; col <= right; col++ ) {
				if( References.CLIENT_VIEW.dungeon[row][col] != this && Toolbox.isLineCrossingRectangle( lineOfSight, References.CLIENT_VIEW.dungeon[row][col].getCollisionBox() )
						&& !References.CLIENT_VIEW.dungeon[row][col].isPassable() ) {
					// Test space!
					return false;
				}
			}
		}
		return true;
	}

	/** @return Two integers relating to the map cell that this object resides in */
	public Vector2f getMapCoordinates() {
		return new Vector2f( (int)( this.position.x / DungeonGenerator.DUNGEON_COL_SIZE ), (int)( this.position.y / DungeonGenerator.DUNGEON_ROW_SIZE ) );
	}

	public Vector2f getCenterPoint() {
		return new Vector2f( this.getCollisionBox().getCenterX(), this.getCollisionBox().getCenterY() );
	}

	public Vector2f getNearestCornerTo(Agent agent) {
		float x, y;
		x = agent.getCenterPoint().x < this.getCenterPoint().x ? this.getCollisionBox().getMinX() : this.getCollisionBox().getMaxX();
		y = agent.getCenterPoint().y < this.getCenterPoint().y ? this.getCollisionBox().getMinY() : this.getCollisionBox().getMaxY();
		return new Vector2f( x, y );
	}

	/** @return the position */
	public Vector2f getPosition() {
		return this.position;
	}

	/** @param position the position to set */
	public void setPosition(Vector2f position) {
		this.position = position;
	}

	public void setPosition(float x, float y) {
		this.position.x = x;
		this.position.y = y;
		this.getCollisionBox().setX( x );
		this.getCollisionBox().setY( y );
	}

	/** @return the collisionBox */
	public Rectangle getCollisionBox() {
		return this.collisionBox;
	}

	/** @param collisionBox the collisionBox to set */
	public void setCollisionBox(Rectangle collisionBox) {
		this.collisionBox = collisionBox;
	}

	/** @param collisionBox the collisionBox to set */
	public void setCollisionBox(float x, float y, float width, float height) {
		this.collisionBox = new Rectangle( x, y, width, height );
	}

	public QuadCollisionEngine getParentNode() {
		return parentNode;
	}

	public void setParentNode(QuadCollisionEngine parentNode) {
		this.parentNode = parentNode;
	}
}
